package algorithms;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Arrays;
import java.util.List;

import dataStructure.HashTreeNode;
import dataStructure.ItemSet;

public class Apriori extends Algo {

	HashTreeNode root;

	public Apriori(String pathFormat, int startIndex, int endIndex) {
		super(pathFormat, startIndex, endIndex);
		root = new HashTreeNode(0);
	}

	@Override
	public HashTreeNode findFrequentItemSet(double support, int minimumK,
			int maxK) {

		BufferedReader br;
		FileReader fr;
		String line;
		String[] tmpBasket;

		root.depth = 0;
		root.set = null;

		int k = 0;
		while (true) {
			iterNum++;
			// For the single tones we are twice as harsh...
			if (k == 1)
				support = support / 2;

			k++;
			numOfItems = 0;
			numOfBaskets = 0;
			for (int i = fileStartIndex; i <= fileEndIndex; i++) {
				try {
					fr = new FileReader(String.format(filePathFormat, i));
					br = new BufferedReader(fr);
					while ((line = br.readLine()) != null) {
						if (line.startsWith("#") || line.equals(""))
							// Ignore comments
							continue;
						else {
							line = line.toLowerCase();
							tmpBasket = line.split(",");
							numOfItems += tmpBasket.length;
							numOfBaskets++;
							newBasket(tmpBasket, k, root);
						}
					}
					br.close();
					fr.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			if (!root.pruneAtDepth(support, numOfBaskets, k))
				break;// There are no more live itemsets of size K
			System.gc();
			if (k == maxK)
				break;
			if (!root.discoverAtDepth(support, numOfBaskets, k))
				break;// Didn't found new itemset, we can break
		}

		return root;
	}

	protected void newBasket(String[] tmpBasket, int k, HashTreeNode root) {
		Arrays.sort(tmpBasket);
		List<List<String>> subsets = Common.getAllSubsets(tmpBasket, k);
		boolean found = true;
		if (subsets == null)
			return;
		HashTreeNode traverser;
		HashTreeNode singletone;
		for (List<String> list : subsets) {
			traverser = root;
			if (traverser.childrens == null)
				continue;
			// Assert(k==list.size())
			for (int i = 0; i < k; i++) {
				String word = list.get(i);
				if (traverser.childrens.containsKey(word)) {
					traverser = traverser.childrens.get(word);
					found = true;
				} else if (k == 1) {
					Algo.incStats(k);
					singletone = new HashTreeNode(1);
					singletone.set = new ItemSet();
					singletone.set.addItem(word);
					traverser.put(word, singletone);
					traverser = traverser.childrens.get(word);
					found = true;
				} else {
					found = false;
					break;
				}
			}
			if (found) {
				traverser.set.counter++;
			}
		}
	}
}
